package scene.shape.materials;
import raytracing.HitRecord;
import scene.Scene;
import scene.lighting.Light;
import scene.shape.geometry.Triangle;
import util.Color3f;
import util.Vector3f;

/**
 * A Phong material (specular lighting)
 * @author glenn
 *
 */
public class PhongMaterial extends Material{
	
	private float shininess;

	public PhongMaterial(Color3f color, float shininess, String name){
		super(color,name);
		this.shininess = shininess;
	}
	
	public Color3f shade(HitRecord hr, Light light, int recursiondepth){
		if(recursiondepth > MAX_RECURSIONDEPTH)
			return new Color3f(0,0,0);
 		Vector3f v = hr.getRay().getDirection().scale(-1),
				 n = hr.getNormal(),
 				 l = light.getPosition().subtract(hr.getIntersectionPoint()).normalize(),
				 h = v.add(l).normalize();
		float cosalpha = Math.max(0,n.dot(h));
	    return getAmbientShading().add(getDiffuseShading(n,l,light)).add(getPhongShading(light,cosalpha));
	}
	
	public Color3f shade(Triangle t, float alpha, float beta, float gamma){
		Color3f c = getAmbientShading();
		Vector3f n = t.getWeightedNormal(alpha, beta, gamma),
				 v = Scene.getInstance().getCurrentCamera().getEye().subtract(t.getPointAt(alpha, beta, gamma)).normalize();
		for(Light light : Scene.getInstance().getLights()){
			Vector3f l = light.getPosition().subtract(t.getPointAt(alpha, beta, gamma)).normalize(),
					 h = v.add(l).normalize();
			float cosalpha = Math.max(0,n.dot(h));
			c = c.add(getDiffuseShading(n,l,light)).add(getPhongShading(light, cosalpha));
		}
		return c;
	}

	private Color3f getPhongShading(Light light, float cosalpha) {
		return color.scale(light.getIntensity() * (float)Math.pow(cosalpha,shininess));
	}
}
